#pragma once
#include <cstdint>
#include <filesystem>
#include "glad/glad.h"


namespace ETextureTypes
{
	// 纹理的环绕方式
	enum WrapAround : int32_t
	{
		// 重复	
		Repeat = GL_REPEAT,
		// 镜像重复
		MirroredRepeat = GL_MIRRORED_REPEAT,
		// 约束的边缘
		ClampToEdge = GL_CLAMP_TO_EDGE,
		// 约束到边 指定边颜色
		ClampToBorder = GL_CLAMP_TO_BORDER,
	};

	// 纹理过滤
	enum Filter : int32_t
	{
		// 邻近过滤  选中心点最近的像素的颜色
		Nearest = GL_NEAREST,

		// 线性过滤  基于纹理坐标附近的纹理像素插值计算
		Linear = GL_LINEAR
	};
}



namespace FFileSys = std::filesystem;

class FTexture2D
{
public:

	auto BindTextureUnit(int8_t UnitIndex) -> void;

	auto GetHandle() const -> uint32_t;  // NOLINT(modernize-use-nodiscard)

	auto GenerateMipmap() const -> void;
private:

	int32_t Width = 0;
	int32_t Height = 0;

	uint32_t TextureHandle = 0;

	friend  class FTextureBuild;
};


class FTextureBuild
{
public:

	[[nodiscard]] auto Build() -> std::shared_ptr<FTexture2D>;

	[[nodiscard]] auto Build(const FFileSys::path& FilePath, bool FlipVertically = false) -> std::shared_ptr<FTexture2D>;

	auto SetTextureData(const int32_t InType, void* InData) -> FTextureBuild&;

	auto SetFormat(const int32_t InFormat) -> FTextureBuild&;

	auto SetInternalFormat(const int32_t InFormat) -> FTextureBuild&;

	auto SetSize(const int32_t W, const int32_t H) -> FTextureBuild&;

	auto SetFilter(const ETextureTypes::Filter InFilter) -> FTextureBuild&;

	auto SetWrapAround(const ETextureTypes::WrapAround InWrapAround) -> FTextureBuild&;

	auto SetImgFileInfo(const FFileSys::path& Path, bool FlipVertically = false) ->FTextureBuild&;

	auto SetGenMinMap(bool Enabled)->FTextureBuild&;

	void Reset();

private:

private:

	bool GenMinMap = false;

	void* Data = nullptr;
	int32_t DataType = GL_UNSIGNED_BYTE;

	int32_t InternalFormat = GL_RGB;
	int32_t Format = GL_RGB;

	int32_t Width = 0;
	int32_t Height = 0;

	glm::vec4 BorderColor = glm::vec4(1.f);

	bool ImgFileFlipVertically = false;
	std::optional<FFileSys::path> ImgFilePath;

	std::optional<ETextureTypes::WrapAround> WrapAround;
	std::optional<ETextureTypes::Filter> Filter;
};